/*
    This file is part of SQLiteGTK, written by Aly Hirani

    SQLiteGTK is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    SQLiteGTK is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with SQLiteGTK.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "include.h"
#include "prefs_manager.h"
#include "util.h"

inline gboolean key_file_key_exists(GKeyFile *key_file, const gchar* group_name, const gchar *key)
{
	GError *error = NULL;
	
	g_assert(key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key != NULL);
	
	if(g_key_file_has_key(key_file, group_name, key, &error))
	{
		return TRUE;
	}
	else
	{
		if(error)
		{
			g_error_free(error);
			error = NULL;
		}
		return FALSE;
	}
}

gboolean prefs_manager_has_key(PrefsManager *prefs_manager, const gchar* group_name, const gchar *key)
{
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key != NULL);
	
	return key_file_key_exists(prefs_manager->key_file, group_name, key);
}

void
prefs_manager_free(PrefsManager *prefs_manager)
{
	gsize length, bytes_written;
	gchar *data;
	GError *error = NULL;
	GIOChannel *io;
	
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(prefs_manager->file_path != NULL);
	
	data = g_key_file_to_data(prefs_manager->key_file, &length, NULL);
	
	io = g_io_channel_new_file(prefs_manager->file_path, "w", &error);
	
	if(error || !io)
	{
		log_error("Unable to open the user preference at: %s\n", prefs_manager->file_path);
		goto cleanup;
	}
	
	if(g_io_channel_write_chars(io, data, length, &bytes_written, &error) != G_IO_STATUS_NORMAL)
	{
		log_error("Unable to write the user preferences!\n");
		goto cleanup;
	}
	
cleanup:
	if(error)
	{
		g_error_free(error);
		error = NULL;
	}
	if(io)
	{
		g_io_channel_shutdown(io, TRUE, &error);
		g_io_channel_unref(io);
		
		if(error)
		{
			g_error_free(error);
			error = NULL;
		}
	}
	g_free(prefs_manager->file_path);
	g_key_file_free(prefs_manager->key_file);
	g_free(prefs_manager);
}

PrefsManager *
prefs_manager_new(const gchar *file_path)
{
	PrefsManager *prefs_manager;
	GKeyFile *key_file;
	GFile *pref_file;
	
	g_assert(file_path != NULL);
	
	prefs_manager = g_malloc(sizeof(prefs_manager));
	g_assert(prefs_manager != NULL);
	
	key_file = prefs_manager->key_file = g_key_file_new();
	g_assert(key_file != NULL);
	
	prefs_manager->file_path = g_strdup(file_path);
	g_assert(prefs_manager->file_path != NULL);
	
	pref_file = g_file_new_for_path(file_path);
	g_assert(pref_file != NULL);
	
	if(g_file_query_exists(pref_file, FALSE))
	{
		if(!g_key_file_load_from_file(key_file, file_path, G_KEY_FILE_KEEP_COMMENTS, NULL))
		{
			log_error("Unable to open user preferences!\n");
		}
	}
	else
	{
		key_file = g_key_file_new();
	}
	
	g_object_unref(pref_file);
	
	return prefs_manager;
}

gint
prefs_manager_get_int(PrefsManager *prefs_manager, const gchar* group_name, const gchar* key_name, gint default_value)
{
	GError *error = NULL;
	gint result;
	
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	result = g_key_file_get_integer(prefs_manager->key_file, group_name, key_name, &error);
	
	if(error)
	{
		g_error_free(error);
		error = NULL;
		
		return default_value;
	}
	else
	{
		return result;
	}
}

void
prefs_manager_set_int(PrefsManager *prefs_manager, const gchar *group_name, const gchar *key_name, gint value)
{
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	g_key_file_set_integer(prefs_manager->key_file, group_name, key_name, value);
}

gboolean
prefs_manager_equals_int(PrefsManager *prefs_manager, const gchar *group_name, const gchar *key_name, gint value)
{
	g_assert(prefs_manager != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	if(prefs_manager_has_key(prefs_manager, group_name, key_name))
	{
		return prefs_manager_get_int(prefs_manager, group_name, key_name, 0) == value;
	}
	else
	{
		return FALSE;
	}
}

gboolean
prefs_manager_get_bool(PrefsManager *prefs_manager, const gchar* group_name, const gchar* key_name, gboolean default_value)
{
	GError *error = NULL;
	gboolean result;
	
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	result = g_key_file_get_boolean(prefs_manager->key_file, group_name, key_name, &error);
	
	if(error)
	{
		g_error_free(error);
		error = NULL;
		
		return default_value;
	}
	else
	{
		return result;
	}
}

void
prefs_manager_set_bool(PrefsManager *prefs_manager, const gchar *group_name, const gchar *key_name, gboolean value)
{
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	g_key_file_set_boolean(prefs_manager->key_file, group_name, key_name, value);
}

gdouble
prefs_manager_get_double(PrefsManager *prefs_manager, const gchar* group_name, const gchar* key_name, gdouble default_value)
{
	GError *error = NULL;
	gdouble result;
	
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	result = g_key_file_get_double(prefs_manager->key_file, group_name, key_name, &error);
	
	if(error)
	{
		g_error_free(error);
		error = NULL;
		
		return default_value;
	}
	else
	{
		return result;
	}
}

void
prefs_manager_set_double(PrefsManager *prefs_manager, const gchar *group_name, const gchar *key_name, gdouble value)
{
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	g_key_file_set_double(prefs_manager->key_file, group_name, key_name, value);
}

gchar *
prefs_manager_get_string(PrefsManager *prefs_manager, const gchar* group_name, const gchar* key_name, const gchar *default_value)
{
	GError *error = NULL;
	gchar *result;
	
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	result = g_key_file_get_string(prefs_manager->key_file, group_name, key_name, &error);
	
	if(error)
	{
		g_error_free(error);
		error = NULL;
		
		if(default_value)
			return g_strdup(default_value);
		else
			return NULL;
	}
	else
	{
		return result;
	}
}

void
prefs_manager_set_string(PrefsManager *prefs_manager, const gchar *group_name, const gchar *key_name, gchar* value)
{
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	g_key_file_set_string(prefs_manager->key_file, group_name, key_name, value);
}

gboolean
prefs_manager_equals_bool(PrefsManager *prefs_manager, const gchar *group_name, const gchar *key_name, gboolean value)
{
	g_assert(prefs_manager != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	if(prefs_manager_has_key(prefs_manager, group_name, key_name))
	{
		return prefs_manager_get_bool(prefs_manager, group_name, key_name, TRUE) == value;
	}
	else
	{
		return FALSE;
	}
}

gboolean
prefs_manager_equals_double(PrefsManager *prefs_manager, const gchar *group_name, const gchar *key_name, gdouble value)
{
	g_assert(prefs_manager != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	if(prefs_manager_has_key(prefs_manager, group_name, key_name))
	{
		return prefs_manager_get_double(prefs_manager, group_name, key_name, 0) == value;
	}
	else
	{
		return FALSE;
	}
}

gboolean
prefs_manager_equals_string(PrefsManager *prefs_manager, const gchar *group_name, const gchar *key_name, gchar* value)
{
	g_assert(prefs_manager != NULL);
	g_assert(group_name != NULL);
	g_assert(key_name != NULL);
	
	if(prefs_manager_has_key(prefs_manager, group_name, key_name))
	{
		return g_str_equal(prefs_manager_get_string(prefs_manager, group_name, key_name, ""), value);
	}
	else
	{
		return FALSE;
	}
}

gchar** prefs_manager_get_keys(PrefsManager *prefs_manager, const gchar* group_name)
{
	g_assert(prefs_manager != NULL);
	g_assert(prefs_manager->key_file != NULL);
	g_assert(group_name != NULL);
	
	return g_key_file_get_keys(prefs_manager->key_file, group_name, NULL, NULL);
}

